#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>


#define DEVICE_NAME "misc_device"
#define BUF_SIZE 100

static char device_buffer[BUF_SIZE] = "Hello, Misc Device!\n";
static volatile unsigned int *GPIO5_DR = NULL;

// 定义模块参数
static int myint = 42;             // 默认值为 42
module_param(myint, int, 0444);    // 参数名为 myint，类型为 int，权限为只读
MODULE_PARM_DESC(myint, "An integer parameter");

static char *mystr = "default";    // 默认值为 "default"
module_param(mystr, charp, 0644);  // 参数名为 mystr，类型为字符串，权限为读写
MODULE_PARM_DESC(mystr, "A string parameter");

static int myarray[10];
static int arrsize = 0;
module_param_array(myarray, int, &arrsize, 0644); // 参数名为 myarray，类型为 int，权限为读写
MODULE_PARM_DESC(myarray, "A int array parameter");


// 设备打开函数
static int misc_open(struct inode *inode, struct file *file)
{
    pr_info("misc_device: opened\n");
    return 0;
}

// 设备关闭函数
static int misc_close(struct inode *inode, struct file *file)
{
    pr_info("misc_device: closed\n");
    return 0;
}

// 设备读函数
static ssize_t misc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    size_t len = strlen(device_buffer);
    int i = 0;
    printk(KERN_INFO "myint = %d\n", myint);
    printk(KERN_INFO "mystr = %s\n", mystr);

    printk(KERN_INFO "arrsize = %d\n", arrsize);
    for(; i < arrsize; i++)
    {
        printk(KERN_INFO "myarray[%d] = %d\n", i, myarray[i]);
    }
    if (*ppos >= len)
        return 0; // 已经读取完

    if (count > len - *ppos)
        count = len - *ppos;

    if (copy_to_user(buf, device_buffer + *ppos, count))
        return -EFAULT;

    *ppos += count;
    return 0;
}

// 设备写函数
static ssize_t misc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    if (count > BUF_SIZE - 1)
        return -EINVAL; // 缓冲区溢出

    if (copy_from_user(device_buffer, buf, count))
        return -EFAULT;
    if(GPIO5_DR == NULL)
    {
        pr_info("GPIO5_DR == NULL\n");
        return -EFAULT;
    }
    device_buffer[count] = '\0'; // 添加字符串结束符
    pr_info("misc_device: received %s\n", device_buffer);

    //led 亮灭控制
    pr_info("device_buffer[0] =  %c\n", device_buffer[0]);
    if(device_buffer[0] == 'o')
    {
        pr_info("LED ON! \n");
        *GPIO5_DR &= ~(1<<3);
    }
    else
    {
        pr_info("LED OFF! \n");
        *GPIO5_DR |= (1<<3);
    }

    return count;
}

// 文件操作结构体
static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = misc_open,
    .release = misc_close,
    .read = misc_read,
    .write = misc_write,
};

// 杂项设备结构体
static struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR, // 随机分配子设备号
    .name = DEVICE_NAME,
    .fops = &fops,
};

// 模块初始化
static int __init misc_init(void)
{
    int ret;

    ret = misc_register(&misc_dev);
    if (ret) {
        pr_err("Failed to register misc device\n");
        return ret;
    }

    GPIO5_DR = ioremap(0x020AC000, 4); //led data io地址映射

    pr_info("misc_device: registered with minor %d\n", misc_dev.minor);
    return 0;
    
}

// 模块卸载
static void __exit misc_exit(void)
{
    misc_deregister(&misc_dev);
    pr_info("misc_device: unregistered\n");
}

module_init(misc_init);
module_exit(misc_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple misc device driver");
MODULE_VERSION("1.0");
